package openjdk.stream;

import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;

import static java.util.stream.Collectors.*;

public class GrpSumWithWhenCase {
    private static class Foo {
        public int id, targetCost;
        public Boolean ref;

        public Foo(int id, boolean ref, int targetCost) {
            this.id = id;
            this.targetCost = targetCost;
            this.ref = ref;
        }

        public int getTargetCost() {
            return this.targetCost;
        }

        @Override
        public String toString() {
            return String.format("(%d,%s,%d)", id, ref, targetCost);
        }
    }

    public static void main(String[] args) {
        List<Foo> list = Arrays.asList(
                new Foo(1, true, 400),
                new Foo(2, true, 400),
                new Foo(3, false, 20),
                new Foo(3, false, 20),
                new Foo(3, false, 20),
                new Foo(1, false, 40),
                new Foo(4, false, 200),
                new Foo(4, false, 900));

        List<Foo> transform = list.stream()
                .collect(groupingBy(foo -> foo.id))
                .entrySet().stream()
                .map(e -> e.getValue().stream()
                        .reduce((f1, f2) -> new Foo(f1.id, f1.ref, f1.targetCost + f2.targetCost)))
                .map(f -> f.get())
                .collect(Collectors.toList());
        System.out.println(transform);

        // group by id 2
        list.stream().collect(groupingBy(foo -> foo.id, collectingAndThen(reducing(
                (a, b) -> new Foo(a.id, a.ref, a.targetCost + b.targetCost)),
                Optional::get)))
                .forEach((id, foo) -> System.out.println(foo));

        // group by id 2
        list.stream().collect(groupingBy(foo -> foo.ref, groupingBy(foo -> foo.id)))
                .forEach((id, foo) -> System.out.println(foo));


        //
        System.out.println(">>>>>>>>>>>>>>>>>>>>>>");


        Map<String, String> productsByNameCategoryType = list.stream()
                .collect(Collectors.groupingBy(p -> "" + p.id + '-' + p.ref.toString(),
                        Collectors.collectingAndThen(
                                Collectors.summarizingDouble(Foo::getTargetCost),
                                dss -> String.format("%7.2f%3d",
                                        dss.getSum(), dss.getCount()))));
        Object obj = null;
        System.out.println(productsByNameCategoryType);

        // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

        Map<String, String> productsByNameCategoryType2 = list.stream()
                .collect(Collectors.groupingBy(p -> "" + p.id + '-' + p.ref.toString(),
                        Collectors.collectingAndThen(
                                Collectors.summarizingDouble(Foo::getTargetCost),
                                dss -> String.format("%7.2f", dss.getSum()))));
        obj = null;
        System.out.println(productsByNameCategoryType2);

        // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

        Map<String, Long> productsByNameCategoryType3 = list.stream()
                .collect(Collectors.groupingBy(p -> "" + p.id + '-' + p.ref.toString(),
                        Collectors.collectingAndThen(
                                Collectors.summarizingInt(Foo::getTargetCost),
                                dss -> dss.getSum())));
        obj = null;
        System.out.println(productsByNameCategoryType3);


    }
}